using System.Collections.Concurrent;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Performance
{
    /// <summary>
    /// 租户性能监控服务接口
    /// 提供租户级别的性能指标收集和分析
    /// </summary>
    public interface ITenantPerformanceService
    {
        Task RecordRequestAsync(string tenantId, string operation, TimeSpan duration, bool success = true);
        Task RecordQueryAsync(string tenantId, string queryType, TimeSpan duration, int resultCount);
        Task RecordCacheOperationAsync(string tenantId, string operation, bool hit, TimeSpan duration);
        Task<TenantPerformanceMetrics> GetMetricsAsync(string tenantId, TimeSpan? timeRange = null);
        Task<List<TenantPerformanceAlert>> GetAlertsAsync(string tenantId);
        Task<TenantPerformanceSummary> GetSummaryAsync(string tenantId);
        IDisposable StartOperation(string tenantId, string operationName);
    }

    /// <summary>
    /// 租户性能监控服务实现
    /// 提供实时性能监控、异常检测和性能优化建议
    /// </summary>
    public class TenantPerformanceService : ITenantPerformanceService
    {
        private readonly ITenantContext _tenantContext;
        private readonly ILogger<TenantPerformanceService> _logger;
        
        // 性能数据存储
        private readonly ConcurrentDictionary<string, List<PerformanceRecord>> _tenantMetrics;
        private readonly ConcurrentDictionary<string, TenantPerformanceThresholds> _tenantThresholds;
        
        // 性能阈值配置
        private readonly TimeSpan _dataRetentionPeriod = TimeSpan.FromHours(24);
        private readonly int _maxRecordsPerTenant = 10000;

        public TenantPerformanceService(
            ITenantContext tenantContext,
            ILogger<TenantPerformanceService> logger)
        {
            _tenantContext = tenantContext;
            _logger = logger;
            _tenantMetrics = new ConcurrentDictionary<string, List<PerformanceRecord>>();
            _tenantThresholds = new ConcurrentDictionary<string, TenantPerformanceThresholds>();
            
            // 启动后台清理任务
            _ = Task.Run(PerformanceDataCleanupAsync);
        }

        /// <summary>
        /// 记录请求性能数据
        /// </summary>
        public async Task RecordRequestAsync(string tenantId, string operation, TimeSpan duration, bool success = true)
        {
            if (string.IsNullOrEmpty(tenantId))
                return;

            var record = new PerformanceRecord
            {
                TenantId = tenantId,
                Operation = operation,
                Duration = duration,
                Success = success,
                RecordType = PerformanceRecordType.Request,
                Timestamp = DateTime.UtcNow
            };

            await AddPerformanceRecordAsync(record);
            
            // 检查性能阈值
            await CheckPerformanceThresholdsAsync(tenantId, record);
        }

        /// <summary>
        /// 记录查询性能数据
        /// </summary>
        public async Task RecordQueryAsync(string tenantId, string queryType, TimeSpan duration, int resultCount)
        {
            if (string.IsNullOrEmpty(tenantId))
                return;

            var record = new PerformanceRecord
            {
                TenantId = tenantId,
                Operation = queryType,
                Duration = duration,
                Success = true,
                RecordType = PerformanceRecordType.Query,
                ResultCount = resultCount,
                Timestamp = DateTime.UtcNow
            };

            await AddPerformanceRecordAsync(record);
        }

        /// <summary>
        /// 记录缓存操作性能数据
        /// </summary>
        public async Task RecordCacheOperationAsync(string tenantId, string operation, bool hit, TimeSpan duration)
        {
            if (string.IsNullOrEmpty(tenantId))
                return;

            var record = new PerformanceRecord
            {
                TenantId = tenantId,
                Operation = operation,
                Duration = duration,
                Success = hit,
                RecordType = PerformanceRecordType.Cache,
                Timestamp = DateTime.UtcNow
            };

            await AddPerformanceRecordAsync(record);
        }

        /// <summary>
        /// 获取租户性能指标
        /// </summary>
        public async Task<TenantPerformanceMetrics> GetMetricsAsync(string tenantId, TimeSpan? timeRange = null)
        {
            if (string.IsNullOrEmpty(tenantId))
                return new TenantPerformanceMetrics { TenantId = tenantId };

            var range = timeRange ?? TimeSpan.FromHours(1);
            var cutoffTime = DateTime.UtcNow - range;
            
            var records = GetTenantRecords(tenantId)
                .Where(r => r.Timestamp >= cutoffTime)
                .ToList();

            var metrics = new TenantPerformanceMetrics
            {
                TenantId = tenantId,
                TimeRange = range,
                TotalRequests = records.Count(r => r.RecordType == PerformanceRecordType.Request),
                SuccessfulRequests = records.Count(r => r.RecordType == PerformanceRecordType.Request && r.Success),
                AverageResponseTime = CalculateAverageResponseTime(records),
                P95ResponseTime = CalculatePercentileResponseTime(records, 95),
                P99ResponseTime = CalculatePercentileResponseTime(records, 99),
                TotalQueries = records.Count(r => r.RecordType == PerformanceRecordType.Query),
                AverageQueryTime = CalculateAverageQueryTime(records),
                CacheHitRatio = CalculateCacheHitRatio(records),
                ErrorRate = CalculateErrorRate(records),
                RequestsPerMinute = CalculateRequestsPerMinute(records, range)
            };

            await Task.CompletedTask;
            return metrics;
        }

        /// <summary>
        /// 获取租户性能告警
        /// </summary>
        public async Task<List<TenantPerformanceAlert>> GetAlertsAsync(string tenantId)
        {
            var alerts = new List<TenantPerformanceAlert>();
            var metrics = await GetMetricsAsync(tenantId, TimeSpan.FromMinutes(15));
            var thresholds = GetTenantThresholds(tenantId);

            // 检查响应时间告警
            if (metrics.AverageResponseTime.TotalMilliseconds > thresholds.ResponseTimeThreshold.TotalMilliseconds)
            {
                alerts.Add(new TenantPerformanceAlert
                {
                    TenantId = tenantId,
                    AlertType = "ResponseTime",
                    Severity = AlertSeverity.Warning,
                    Message = $"平均响应时间 {metrics.AverageResponseTime.TotalMilliseconds:F2}ms 超过阈值 {thresholds.ResponseTimeThreshold.TotalMilliseconds}ms",
                    Timestamp = DateTime.UtcNow,
                    Value = metrics.AverageResponseTime.TotalMilliseconds,
                    Threshold = thresholds.ResponseTimeThreshold.TotalMilliseconds
                });
            }

            // 检查错误率告警
            if (metrics.ErrorRate > thresholds.ErrorRateThreshold)
            {
                alerts.Add(new TenantPerformanceAlert
                {
                    TenantId = tenantId,
                    AlertType = "ErrorRate",
                    Severity = AlertSeverity.Critical,
                    Message = $"错误率 {metrics.ErrorRate:P2} 超过阈值 {thresholds.ErrorRateThreshold:P2}",
                    Timestamp = DateTime.UtcNow,
                    Value = metrics.ErrorRate,
                    Threshold = thresholds.ErrorRateThreshold
                });
            }

            // 检查缓存命中率告警
            if (metrics.CacheHitRatio < thresholds.CacheHitRatioThreshold)
            {
                alerts.Add(new TenantPerformanceAlert
                {
                    TenantId = tenantId,
                    AlertType = "CacheHitRatio",
                    Severity = AlertSeverity.Warning,
                    Message = $"缓存命中率 {metrics.CacheHitRatio:P2} 低于阈值 {thresholds.CacheHitRatioThreshold:P2}",
                    Timestamp = DateTime.UtcNow,
                    Value = metrics.CacheHitRatio,
                    Threshold = thresholds.CacheHitRatioThreshold
                });
            }

            return alerts;
        }

        /// <summary>
        /// 获取租户性能摘要
        /// </summary>
        public async Task<TenantPerformanceSummary> GetSummaryAsync(string tenantId)
        {
            var last15Min = await GetMetricsAsync(tenantId, TimeSpan.FromMinutes(15));
            var lastHour = await GetMetricsAsync(tenantId, TimeSpan.FromHours(1));
            var last24Hours = await GetMetricsAsync(tenantId, TimeSpan.FromHours(24));

            return new TenantPerformanceSummary
            {
                TenantId = tenantId,
                Last15Minutes = last15Min,
                LastHour = lastHour,
                Last24Hours = last24Hours,
                Recommendations = await GenerateRecommendationsAsync(tenantId, last24Hours)
            };
        }

        /// <summary>
        /// 开始操作性能跟踪
        /// </summary>
        public IDisposable StartOperation(string tenantId, string operationName)
        {
            return new OperationTracker(this, tenantId, operationName);
        }

        #region 私有方法

        /// <summary>
        /// 添加性能记录
        /// </summary>
        private async Task AddPerformanceRecordAsync(PerformanceRecord record)
        {
            var records = _tenantMetrics.GetOrAdd(record.TenantId, _ => new List<PerformanceRecord>());
            
            lock (records)
            {
                records.Add(record);
                
                // 限制记录数量
                if (records.Count > _maxRecordsPerTenant)
                {
                    records.RemoveRange(0, records.Count - _maxRecordsPerTenant);
                }
            }

            await Task.CompletedTask;
        }

        /// <summary>
        /// 获取租户记录
        /// </summary>
        private List<PerformanceRecord> GetTenantRecords(string tenantId)
        {
            if (_tenantMetrics.TryGetValue(tenantId, out var records))
            {
                lock (records)
                {
                    return new List<PerformanceRecord>(records);
                }
            }
            return new List<PerformanceRecord>();
        }

        /// <summary>
        /// 检查性能阈值
        /// </summary>
        private async Task CheckPerformanceThresholdsAsync(string tenantId, PerformanceRecord record)
        {
            var thresholds = GetTenantThresholds(tenantId);
            
            if (record.Duration > thresholds.ResponseTimeThreshold)
            {
                _logger.LogWarning("租户 {TenantId} 操作 {Operation} 响应时间 {Duration}ms 超过阈值 {Threshold}ms",
                    tenantId, record.Operation, record.Duration.TotalMilliseconds, thresholds.ResponseTimeThreshold.TotalMilliseconds);
            }

            await Task.CompletedTask;
        }

        /// <summary>
        /// 获取租户阈值配置
        /// </summary>
        private TenantPerformanceThresholds GetTenantThresholds(string tenantId)
        {
            return _tenantThresholds.GetOrAdd(tenantId, _ => new TenantPerformanceThresholds());
        }

        /// <summary>
        /// 计算平均响应时间
        /// </summary>
        private TimeSpan CalculateAverageResponseTime(List<PerformanceRecord> records)
        {
            var requestRecords = records.Where(r => r.RecordType == PerformanceRecordType.Request).ToList();
            if (!requestRecords.Any())
                return TimeSpan.Zero;

            var totalMs = requestRecords.Sum(r => r.Duration.TotalMilliseconds);
            return TimeSpan.FromMilliseconds(totalMs / requestRecords.Count);
        }

        /// <summary>
        /// 计算百分位响应时间
        /// </summary>
        private TimeSpan CalculatePercentileResponseTime(List<PerformanceRecord> records, int percentile)
        {
            var requestRecords = records
                .Where(r => r.RecordType == PerformanceRecordType.Request)
                .OrderBy(r => r.Duration)
                .ToList();

            if (!requestRecords.Any())
                return TimeSpan.Zero;

            var index = (int)Math.Ceiling((percentile / 100.0) * requestRecords.Count) - 1;
            index = Math.Max(0, Math.Min(index, requestRecords.Count - 1));
            
            return requestRecords[index].Duration;
        }

        /// <summary>
        /// 计算平均查询时间
        /// </summary>
        private TimeSpan CalculateAverageQueryTime(List<PerformanceRecord> records)
        {
            var queryRecords = records.Where(r => r.RecordType == PerformanceRecordType.Query).ToList();
            if (!queryRecords.Any())
                return TimeSpan.Zero;

            var totalMs = queryRecords.Sum(r => r.Duration.TotalMilliseconds);
            return TimeSpan.FromMilliseconds(totalMs / queryRecords.Count);
        }

        /// <summary>
        /// 计算缓存命中率
        /// </summary>
        private double CalculateCacheHitRatio(List<PerformanceRecord> records)
        {
            var cacheRecords = records.Where(r => r.RecordType == PerformanceRecordType.Cache).ToList();
            if (!cacheRecords.Any())
                return 0;

            var hits = cacheRecords.Count(r => r.Success);
            return (double)hits / cacheRecords.Count;
        }

        /// <summary>
        /// 计算错误率
        /// </summary>
        private double CalculateErrorRate(List<PerformanceRecord> records)
        {
            var requestRecords = records.Where(r => r.RecordType == PerformanceRecordType.Request).ToList();
            if (!requestRecords.Any())
                return 0;

            var errors = requestRecords.Count(r => !r.Success);
            return (double)errors / requestRecords.Count;
        }

        /// <summary>
        /// 计算每分钟请求数
        /// </summary>
        private double CalculateRequestsPerMinute(List<PerformanceRecord> records, TimeSpan timeRange)
        {
            var requestCount = records.Count(r => r.RecordType == PerformanceRecordType.Request);
            var minutes = timeRange.TotalMinutes;
            return minutes > 0 ? requestCount / minutes : 0;
        }

        /// <summary>
        /// 生成性能优化建议
        /// </summary>
        private async Task<List<string>> GenerateRecommendationsAsync(string tenantId, TenantPerformanceMetrics metrics)
        {
            var recommendations = new List<string>();

            if (metrics.AverageResponseTime > TimeSpan.FromMilliseconds(500))
            {
                recommendations.Add("平均响应时间较高，建议优化数据库查询或增加缓存");
            }

            if (metrics.CacheHitRatio < 0.8)
            {
                recommendations.Add("缓存命中率较低，建议优化缓存策略或预热关键数据");
            }

            if (metrics.ErrorRate > 0.01)
            {
                recommendations.Add("错误率较高，建议检查异常日志并修复问题");
            }

            if (metrics.P95ResponseTime > TimeSpan.FromSeconds(2))
            {
                recommendations.Add("95%响应时间超过2秒，建议优化慢查询");
            }

            await Task.CompletedTask;
            return recommendations;
        }

        /// <summary>
        /// 后台数据清理任务
        /// </summary>
        private async Task PerformanceDataCleanupAsync()
        {
            while (true)
            {
                try
                {
                    var cutoffTime = DateTime.UtcNow - _dataRetentionPeriod;
                    
                    foreach (var kvp in _tenantMetrics.ToList())
                    {
                        var records = kvp.Value;
                        lock (records)
                        {
                            var toRemove = records.Where(r => r.Timestamp < cutoffTime).ToList();
                            foreach (var record in toRemove)
                            {
                                records.Remove(record);
                            }
                        }
                    }

                    await Task.Delay(TimeSpan.FromMinutes(5)); // 每5分钟清理一次
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "性能数据清理任务异常");
                    await Task.Delay(TimeSpan.FromMinutes(1));
                }
            }
        }

        #endregion
    }

    #region 数据模型

    /// <summary>
    /// 性能记录
    /// </summary>
    public class PerformanceRecord
    {
        public string TenantId { get; set; } = string.Empty;
        public string Operation { get; set; } = string.Empty;
        public TimeSpan Duration { get; set; }
        public bool Success { get; set; }
        public PerformanceRecordType RecordType { get; set; }
        public int? ResultCount { get; set; }
        public DateTime Timestamp { get; set; }
    }

    /// <summary>
    /// 性能记录类型
    /// </summary>
    public enum PerformanceRecordType
    {
        Request,
        Query,
        Cache
    }

    /// <summary>
    /// 租户性能指标
    /// </summary>
    public class TenantPerformanceMetrics
    {
        public string TenantId { get; set; } = string.Empty;
        public TimeSpan TimeRange { get; set; }
        public int TotalRequests { get; set; }
        public int SuccessfulRequests { get; set; }
        public TimeSpan AverageResponseTime { get; set; }
        public TimeSpan P95ResponseTime { get; set; }
        public TimeSpan P99ResponseTime { get; set; }
        public int TotalQueries { get; set; }
        public TimeSpan AverageQueryTime { get; set; }
        public double CacheHitRatio { get; set; }
        public double ErrorRate { get; set; }
        public double RequestsPerMinute { get; set; }
    }

    /// <summary>
    /// 租户性能告警
    /// </summary>
    public class TenantPerformanceAlert
    {
        public string TenantId { get; set; } = string.Empty;
        public string AlertType { get; set; } = string.Empty;
        public AlertSeverity Severity { get; set; }
        public string Message { get; set; } = string.Empty;
        public DateTime Timestamp { get; set; }
        public double Value { get; set; }
        public double Threshold { get; set; }
    }

    /// <summary>
    /// 告警级别
    /// </summary>
    public enum AlertSeverity
    {
        Info,
        Warning,
        Critical
    }

    /// <summary>
    /// 租户性能摘要
    /// </summary>
    public class TenantPerformanceSummary
    {
        public string TenantId { get; set; } = string.Empty;
        public TenantPerformanceMetrics Last15Minutes { get; set; } = new();
        public TenantPerformanceMetrics LastHour { get; set; } = new();
        public TenantPerformanceMetrics Last24Hours { get; set; } = new();
        public List<string> Recommendations { get; set; } = new();
    }

    /// <summary>
    /// 租户性能阈值配置
    /// </summary>
    public class TenantPerformanceThresholds
    {
        public TimeSpan ResponseTimeThreshold { get; set; } = TimeSpan.FromMilliseconds(1000);
        public double ErrorRateThreshold { get; set; } = 0.05; // 5%
        public double CacheHitRatioThreshold { get; set; } = 0.8; // 80%
        public double RequestsPerMinuteThreshold { get; set; } = 1000;
    }

    /// <summary>
    /// 操作跟踪器
    /// </summary>
    public class OperationTracker : IDisposable
    {
        private readonly ITenantPerformanceService _performanceService;
        private readonly string _tenantId;
        private readonly string _operationName;
        private readonly Stopwatch _stopwatch;

        public OperationTracker(ITenantPerformanceService performanceService, string tenantId, string operationName)
        {
            _performanceService = performanceService;
            _tenantId = tenantId;
            _operationName = operationName;
            _stopwatch = Stopwatch.StartNew();
        }

        public void Dispose()
        {
            _stopwatch.Stop();
            _ = _performanceService.RecordRequestAsync(_tenantId, _operationName, _stopwatch.Elapsed);
        }
    }

    #endregion
}
